import copy
import pymysql
import yaml
from requests import Response
from commons.extract_util import ExtractUtil
from configs import setting
from commons.request_util import logger


class AssertUtil:
    # 创建数据库链接，pymysql和mysqlclient
    @staticmethod
    def create_connection():
        """
        创建数据库链接
        :return: 返回数据库连接对象
        """
        conn = pymysql.connect(
            user=setting.db_user,
            password=setting.db_password,
            host=setting.db_host,
            database=setting.db_database,
            port=setting.db_port
        )
        return conn

    # 执行SQL语句
    @staticmethod
    def execute_sql(sql):
        """
        执行 SQL 语句，获取执行结果
        :param sql: 需要执行的语句
        :return: 返回执行后结果
        """
        # 创建链接
        conn = AssertUtil.create_connection()
        # 创建游标
        cs = conn.cursor()
        # 执行sql
        cs.execute(sql)
        # 取值
        value = cs.fetchone()
        # 关闭
        cs.close()
        conn.close()
        return value

    # 处理所有的断言
    @staticmethod
    def assert_all(resp: Response, assert_type: str, assert_content: dict):
        """
        执行用例断言
        :param resp: 请求返回的 Response
        :param assert_type: 断言的类型
        :param assert_content: 断言的具体内容
        """
        # 深拷贝一个 response（深拷贝，浅拷贝）
        resp = copy.deepcopy(resp)
        # 循环断言内容
        for msg, data in assert_content.items():
            expr, compare = data["expr"], data["compare"]
            extract_value = ExtractUtil.find_expr(resp, *expr)
            # 实际结果的类型从字典转化成字符串
            if isinstance(extract_value, dict):
                extract_value = yaml.dump(extract_value, allow_unicode=True)
            # 断言
            # logger.info(f"{msg}\ncompare = {compare}\nextract_value = {extract_value}")
            match assert_type:
                case "equals":
                    assert compare == extract_value, msg
                case "contains":
                    assert compare in extract_value, msg
                case "db_equals":
                    value = AssertUtil.execute_sql(compare)
                    if value:
                        assert value[0] == extract_value, msg
                case "db_contains":
                    value = AssertUtil.execute_sql(compare)
                    if value:
                        assert value[0] in extract_value, msg
